package team.hyznrj.studentsys.entity;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * Excel单元格
 * 
 * @author 郑泽锋
 * @date 2018年5月2日
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ExcelUnitObject {
	/**
	 * 起始坐标x
	 */
	private int x;
	/**
	 * 起始坐标y
	 */
	private int y;
	/**
	 * 单元格宽 偏移量,为0时表示只占1格
	 */
	private int width;
	/**
	 * 单元格高 偏移量,为0时表示只占1格
	 */
	private int high;
	/**
	 * 单元值
	 */
	private String value;
	/**
	 * ----- 其他属性 -----
	 */
	/** 该单元格需要的行高值 */
	private int valueHeight = 1;
	/** 该单元格需要的列宽值 */
	private int valueWidth = 1;
	/**
	 * 单元格排列方式
	 */
	private short unitAliginStyle = -1;
	private short unitVerticalStyle = -1;
	/**
	 * 单元格字体大小
	 */
	private int fontSize=9;
	/**
	 * 字体样式
	 */
	private String fontName="宋体";
	/**
	 * 是否加粗
	 * 默认为false
	 */
	private boolean bold=false;
	/**
	 * excel单元格样式
	 * 0000分别代表 上下左右
	 * 1111表示 全框
	 */
	private String excelStyle="1111";
	@Override
	protected ExcelUnitObject clone()  {
		ExcelUnitObject tmp=new ExcelUnitObject();
		tmp.x=this.x;
		tmp.y=this.y;
		tmp.width=this.width;
		tmp.high=this.high;
		tmp.value=this.value;
		tmp.valueHeight=this.valueHeight;
		tmp.valueWidth=this.valueWidth;
		tmp.unitAliginStyle=this.unitAliginStyle;
		tmp.unitVerticalStyle=this.unitVerticalStyle;
		return tmp;
	}
	
	/**
	 * 默认字符串长度(3)
	 */
	private static final int DEFAULT_ONE_STRING_LENGTH = "表".getBytes().length;
	/**
	 * 默认行高字符串个数
	 */
	private static final int DEFAULT_LENGTH = 8;
	/**
	 * 字符宽度(单位:像素点)
	 */
	private static final int DEFAULT_STRING_WIDTH=8;
	
	/**
	 * 获取字符宽
	 * @param val
	 * @return
	 */
	private int getLength(final double val){
		/**
		 * POI中的字符宽度算法是：
		 * double 宽度 = (字符个数 * (字符宽度 - 1) + 5) / (字符宽度 - 1) * 256;
		 * 然后再四舍五入成整数。
		 */
		int result=(int)
				( (val*DEFAULT_ONE_STRING_LENGTH)*(DEFAULT_STRING_WIDTH-1)+6)
				/(DEFAULT_STRING_WIDTH-1)  *256;
		return result;
	}
	/**
	 * 获取像素高
	 * @param val
	 * @return
	 */
	private int getHeighth_(final double val){
		/**
		 * x/72 *96*字体
		 * 13.5?
		 */
//		int result=(int) (DEFAULT_PIXEL_HEIGHTH/72*96*DEFAULT_FONT_SIZE*(val));
		int result=(int)
				( (val*DEFAULT_ONE_STRING_LENGTH)*(DEFAULT_STRING_WIDTH-1)+5)
				/(DEFAULT_STRING_WIDTH-1)  *128;
				//(int) (DEFAULT_PIXEL_HEIGHTH/96 *72*20*(val+1));
		return result;
	}
	/**
	 * 获取字符串的占EXCEL格长（单位：1）
	 * @param value
	 * @return
	 */
	public double getStringBit(final String value){
		double tmp=0;
		for(int i=0;i<value.length();i++){
			char c = value.charAt(i);
			if(c>='0'&&c<='9'){
				tmp+=0.33;
			}else if(c>='a'&&c<='z'){
				tmp+=0.33;
			}else if(c>='A'&&c<='Z'){
				tmp+=0.5;
			}else if(c=='.'){
				tmp+=0.45;
			}else{
				tmp+=0.75;
			}
		}
		return tmp;
	}
	/**
	 * 向上取整
	 * @param value
	 * @return
	 */
	private int convertToUpInt(final double value){
		return (value==(int)value)? (int)value:(int)value+1;
	}
	/**
	 * 设置基本属性
	 * @param locationX
	 * @param locationY
	 * @param i
	 * @param j
	 * @param value2
	 */
	private void setAttrbute(int locationX, int locationY, int i, int j, String value2 ){
		this.x = locationX;
		this.y = locationY;
		this.width = i;
		this.high = j;
		this.value = value2;
		this.unitAliginStyle = HSSFCellStyle.ALIGN_CENTER;
		this.unitVerticalStyle = HSSFCellStyle.VERTICAL_CENTER;
	}
	/**
	 * 设置行高列宽属性
	 * @param value2
	 * @param header
	 */
	private void setWidAndHigh(String value2, boolean header){
		double tmp=getStringBit(value2);
		double w=0,h=0;
		if (header) {
			/**
			 *TODO字符串和数字的大小是不一样的，所以这里需要先获取正真的字符串大小
			 *注意:字符=2个数字的大小
			 * 如果是表头，则用DEFAULT_LENGTH作为列宽行高
			 */
			w=tmp>DEFAULT_LENGTH?    1*convertToUpInt(tmp/DEFAULT_LENGTH):1;
			if(convertToUpInt(tmp)>DEFAULT_LENGTH){
				h=DEFAULT_LENGTH;
			}else{
				h=tmp;
			}
			h*=0.95;
		} else {
			w=tmp;
			h = 0.75;
		}
		valueWidth =getLength(w);
		valueHeight =getHeighth_(h);
	}
	/**
	 * 构造器
	 * @param locationX 坐标x
	 * @param locationY 坐标y
	 * @param i Excel合并单元格的右偏移
	 * @param j Excel合并单元格的下偏移
	 * @param value2 值
	 * @param highBit 字体高度(占几个字高)
	 * @param fontSize 字体大小(比如11号字)
	 */
	public ExcelUnitObject(int locationX, int locationY, int i, int j, String value2 ,int highBit,int fontSize ) {
		this.fontSize=fontSize;
		this.setAttrbute(locationX,locationY,i,j,value2);
		double tmp=getStringBit(value2);
		this.valueWidth =getLength(tmp);
		this.valueHeight =getHeighth_(highBit);
		this.bold=true;
	}
	
	/**
	 * 构造器
	 * @param locationX 坐标x
	 * @param locationY 坐标y
	 * @param i Excel合并单元格的右偏移
	 * @param j Excel合并单元格的下偏移
	 * @param value2   值
	 * @param header 为true则以默认(8)字符为基数垂直分布,false则平铺
	 */
	public ExcelUnitObject(int locationX, int locationY, int i, int j, String value2, boolean header) {
		setAttrbute(locationX,locationY,i,j,value2);
		this.bold=false;
		setWidAndHigh(value2,header);
	}
	/**
	 * 构造器
	 * @param locationX 坐标x
	 * @param locationY 坐标y
	 * @param i Excel合并单元格的右偏移
	 * @param j Excel合并单元格的下偏移
	 * @param value2   值
	 * @param header 为true则以默认(8)字符为基数垂直分布,false则平铺
	 */
	public ExcelUnitObject(int locationX, int locationY, int i, int j, String value2, boolean header,boolean bold) {
		this.setAttrbute(locationX,locationY,i,j,value2);
		this.bold=bold;
		this.setWidAndHigh(value2,header);
	}
}
